using System;
using System.Runtime.CompilerServices;

namespace Net
{
	public struct Bounds : IEquatable<Bounds>
	{
		public Vector3 Center;
		public Vector3 Extents;

		public Bounds(Vector3 center, Vector3 size)
		{
			this.Center = center;
			this.Extents = size * 0.5f;
		}

		public override int GetHashCode()
		{
			return Center.GetHashCode() ^ Extents.GetHashCode() << 2;
		}

		public override bool Equals(object other)
		{
			bool flag = !(other is Bounds);
			return !flag && Equals((Bounds)other);
		}

		public bool Equals(Bounds other)
		{
			return Center.Equals(other.Center) && Extents.Equals(other.Extents);
		}

		public Vector3 size
		{
			get
			{
				return Extents * 2f;
			}
			set
			{
				Extents = value * 0.5f;
			}
		}

		public Vector3 min
		{
			get
			{
				return Center - Extents;
			}
			set
			{
				SetMinMax(value, max);
			}
		}

		public Vector3 max
		{
			get
			{
				return Center + Extents;
			}
			set
			{
				SetMinMax(min, value);
			}
		}

		public static bool operator ==(Bounds lhs, Bounds rhs)
		{
			return lhs.Center == rhs.Center && lhs.Extents == rhs.Extents;
		}

		public static bool operator !=(Bounds lhs, Bounds rhs)
		{
			return !(lhs == rhs);
		}

		public void SetMinMax(Vector3 min, Vector3 max)
		{
			Extents = (max - min) * 0.5f;
			Center = min + Extents;
		}

		public void Encapsulate(Vector3 point)
		{
			SetMinMax(Vector3.Min(min, point), Vector3.Max(max, point));
		}

		public void Encapsulate(Bounds bounds)
		{
			Encapsulate(bounds.Center - bounds.Extents);
			Encapsulate(bounds.Center + bounds.Extents);
		}

		public void Expand(float amount)
		{
			amount *= 0.5f;
			Extents += new Vector3(amount, amount, amount);
		}

		public void Expand(Vector3 amount)
		{
			Extents += amount * 0.5f;
		}

		public bool Intersects(Bounds bounds)
		{
			var min = this.min;
			var max = this.max;
			var otherMin = bounds.min;
			var otherMax = bounds.max;
			if (min.x > otherMax.x)
				return false;
			if (max.x < otherMin.x)
				return false;
			if (min.y > otherMax.y)
				return false;
			if (max.y < otherMin.y)
				return false;
			if (min.z > otherMax.z)
				return false;
			if (max.z < otherMin.z)
				return false;
			return true;
        }

		public override string ToString()
		{
			return $"Center: {Center}, Extents: {Extents}";
		}

		public string ToString(string format)
		{
			return $"Center: {Center.ToString(format)}, Extents: {Extents.ToString(format)}";
		}

		public bool Contains(Vector3 point)
        {
            return point.x >= min.x && point.x <= max.x && point.y >= min.y && point.y <= max.y && point.z >= min.z && point.z <= max.z;
        }
	}
}
